package com.g.code.ebookssync.action;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sf.json.JSONObject;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;

import com.g.code.ebookssync.dao.BooksDao;
import com.g.code.ebookssync.pojo.EBook;
import com.g.code.ebookssync.pojo.User;
import com.g.code.ebookssync.pojo.UserConf;
import com.g.code.ebookssync.pojo.UserEbook;
import com.g.code.ebookssync.service.UploadService;
import com.kuaipan.client.KuaipanAPI;
import com.kuaipan.client.exception.KuaipanAuthExpiredException;
import com.kuaipan.client.exception.KuaipanIOException;
import com.kuaipan.client.exception.KuaipanServerException;
import com.kuaipan.client.model.AccessToken;
import com.kuaipan.client.model.KuaipanUser;
import com.kuaipan.client.model.TokenPair;
import com.kuaipan.client.session.OauthSession;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.sina.sae.fetchurl.SaeFetchurl;
import com.sina.sae.storage.SaeStorage;


@Controller
@Scope("prototype")
public class BooksAction extends ActionSupport {
    
    private static final long serialVersionUID = 1L;
    
    private static Log log = LogFactory.getLog(BooksAction.class);
    private static String SESSION_ATTR_USERID = "_login_userid";
    private static String SESSION_ATTR_ISLOGIN = "_islogin";
    private static String REDIRECT = "redirect";
    private List<EBook> books = null;
    // 电子书的订阅状态
    private Map<String, Long> userBooks = new HashMap<String, Long>();
    
    private long id;
    private String code = null;
    
    private String redirectUrl = null;
    private String sinaLoginUrl = getText("sinaLoginUrl");
    private String accessTokenUrl = getText("accessTokenUrl");
    private String kuaipanConsumerKey = getText("kuaipanConsumerKey");
    private String kuaipanConsumerSecret = getText("kuaipanConsumerSecret");
    private String kuaipanOauthCallbackUrl = getText("kuaipanOauthCallbackUrl");
    private boolean debug = Boolean.parseBoolean(getText("debug"));
    private String contextPath = getText("contextPath");
    
    @Autowired
    private BooksDao booksDao;
    
    @Autowired
    private UploadService uploadService; 
    
    public long getId() {
        return id = -1;
    }
    
    public void setId(long id) {
        this.id = id;
    }

    public String getCode() {
        return code;
    }
    
    public void setCode(String code) {
        this.code = code;
    }

    public List<EBook> getBooks() {
        return books;
    }

    public String getRedirectUrl() {
        return redirectUrl;
    }

    public Map<String, Long> getUserBooks() {
        return userBooks;
    }

    public String getContextPath() {
        return contextPath;
    }

    public String list() {
        books = booksDao.getAllEbook();
//        booksStatus.
        if (isLogin()) {
            String userId = getLoginUserId();
            List<UserEbook> userEbooks = booksDao.getUserEbooks(userId);
            for (UserEbook ue : userEbooks) {
                userBooks.put(String.valueOf(ue.getEbook_id()), ue.getId());
            }
        }
        if (code != null) {
            addActionMessage(getText(code));
        }
        
        return SUCCESS;
    }

    public String subscription() {
        if (!isLogin()) {
            return login();
        }
        String userId = getLoginUserId();
        // 获取可访问的网盘
        List<UserConf> userConfs = booksDao.getUserConfigs(userId);
        if (userConfs.isEmpty()) {
            return requestToken();
        }
        
        // 可能有多个网盘，但目前只处理一个
        if (userConfs.size() != 1) {
            log.error("Find [" + userConfs.size() + "] UserConfig, please check conf status." );
        }
        UserConf conf = userConfs.get(0);
        KuaipanAPI api = getKuaipanAPI();
        AccessToken t = loadAccessToken(conf.getAccess_key());
        if (t != null) {
            api.getSession().setAuthToken(t.key, t.secret);
        }
        
        // 需要重新授权
        if (!api.getSession().isAuth()) {
            requestToken();
            return REDIRECT;
        }
        UserEbook ue = new UserEbook(Long.parseLong(userId), id);
        booksDao.addUserEbook(ue);
        
//        try {
//            System.out.println(api.accountInfo());
//        } catch (KuaipanIOException e) {
//            log.error(e.getMessage(), e);
//        } catch (KuaipanServerException e) {
//            log.error(e.getMessage(), e);
//        } catch (KuaipanAuthExpiredException e) {
//            log.error(e.getMessage(), e);
//        }
        uploadFile(String.valueOf(id), api);
        
        redirectUrl = contextPath + "/books/list.action?code=success_subscription";
        return REDIRECT;
    }
    
    public String unsubscription() {
        if (!isLogin()) {
            return login();
        }
        booksDao.delUserEbook(String.valueOf(id));
        redirectUrl = contextPath + "/books/list.action?code=success_unsubscription";
        return REDIRECT;
    }

    private String getLoginUserId() {
        Map<String, Object> session = ActionContext.getContext().getSession();
        return (String) session.get(SESSION_ATTR_USERID);
    }
    
    private boolean isLogin() {
        Map<String, Object> session = ActionContext.getContext().getSession();
        return Boolean.TRUE.equals(session.get(SESSION_ATTR_ISLOGIN)) ;
    }

    public String login() {
        redirectUrl = sinaLoginUrl;
        return REDIRECT;
    }
    public String logout() {
        ActionContext.getContext().getSession().remove(SESSION_ATTR_USERID);
        ActionContext.getContext().getSession().put(SESSION_ATTR_ISLOGIN, Boolean.FALSE);
        redirectUrl = contextPath + "/books/list.action";
        return REDIRECT;
    }

    private void uploadFile(final String bookId, final KuaipanAPI api) {
        // 异步同步 TODO 需要改进
//        new Thread(new Runnable() {
//            public void run() {
                uploadService.uploadFile(bookId, api);
//            }
//        }).start();
    }

    private AccessToken loadAccessToken(String access_key) {
        String[] token = access_key.split(";");
        return new AccessToken(token[0].split("=")[1], token[1].split("=")[1]);
    }

    private String requestToken() {
        try {
            KuaipanAPI api = getKuaipanAPI();
            String url = api.requestToken(kuaipanOauthCallbackUrl + id);
            ActionContext.getContext().getSession().put("kuaipan_api", api);
            redirectUrl = url;
        } catch (KuaipanIOException e) {
            log.error(e.getMessage(), e);
            redirectUrl = contextPath + "/books/list.action?code=error_kuaipan";
        } catch (KuaipanServerException e) {
            log.error(e.getMessage(), e);
            redirectUrl = contextPath + "/books/list.action?code=error_kuaipan";
        } catch (KuaipanAuthExpiredException e) {
            log.error(e.getMessage(), e);
            redirectUrl = contextPath + "/books/list.action?code=error_kuaipan";
        }
        return REDIRECT;
    }

    private KuaipanAPI getKuaipanAPI() {
        KuaipanAPI api = (KuaipanAPI) ActionContext.getContext().getSession().get("kuaipan_api");
        if (api != null) {
            return api;
        }
        OauthSession oauthSession = new OauthSession(kuaipanConsumerKey, kuaipanConsumerSecret, OauthSession.Root.APP_FOLDER);
        return new KuaipanAPI(oauthSession);
    }
    
    public String sinalogin() {
        if (debug) {
            Map<String, Object> session = ActionContext.getContext().getSession();
            session.put(SESSION_ATTR_USERID, "1");
            session.put(SESSION_ATTR_ISLOGIN, Boolean.TRUE);
        } else {
            SaeFetchurl fetchurl = new SaeFetchurl("w0xlymnzz5", "0ikmkm5hm2m1x5j2jk32300h2y15h2h4hjmlx2wh");
            fetchurl.setMethod("POST");
            fetchurl.fetch(accessTokenUrl + code);
            
            String body = fetchurl.body();
            // 获取access_coken 和 uid
            JSONObject result = JSONObject.fromObject(body);
//        System.out.println(result);
//        String accessToken = result.getString("access_token");
            if (!result.containsKey("uid")) {// 登录失败
                log.error("sinalogin fail");
                addActionMessage(body);
                return ERROR;
            }
            String uid = result.getString("uid");
//        String getUserUrl = String.format(userInfoUrl, accessToken, uid);
            
            // 查询用户信息
//        fetchurl.fetch(getUserUrl);
//        JSONObject userInfo = JSONObject.fromObject(fetchurl.body());
            
            // 在本系统查询用户
            User u = booksDao.getUserById(uid);
            
            if (u == null) {
                booksDao.addUser(uid);
            }
            
            Map<String, Object> session = ActionContext.getContext().getSession();
            session.put(SESSION_ATTR_USERID, uid);
            session.put(SESSION_ATTR_ISLOGIN, Boolean.TRUE);
        }
        redirectUrl = contextPath + "/books/list.action";
        return REDIRECT;
    }

    public String authKuaipan() {
        
        Map<String, Object> session = ActionContext.getContext().getSession();
        
        // 验证登录 
        if (!session.containsKey(SESSION_ATTR_USERID)) {
            login();
            return REDIRECT;
        }
        
        String userId = (String) session.get(SESSION_ATTR_USERID);
        
        KuaipanAPI api = getKuaipanAPI();
        try {
            api.accessToken();
            if (api.getSession().isAuth()) {
                TokenPair token = api.getSession().token;
                KuaipanUser kUser = api.accountInfo();
                
                UserConf userConf = new UserConf();
                userConf.setAccess_key(token.toString());
                userConf.setLogin_name(kUser.user_name);
                userConf.setStorage_type(1); // 1快盘
                userConf.setUser_id(Long.parseLong(userId));
                userConf.setSync_state(1);
                booksDao.addUserConf(userConf);
            }
        } catch (KuaipanIOException e) {
            e.printStackTrace();
        } catch (KuaipanServerException e) {
            e.printStackTrace();
        } catch (KuaipanAuthExpiredException e) {
            e.printStackTrace();
        }
        
        redirectUrl = contextPath + "/books/subscription.action?id=" + id;
        return REDIRECT;
    }
    
    public String test() {
        
        SaeStorage storage = new SaeStorage("w0xlymnzz5","0ikmkm5hm2m1x5j2jk32300h2y15h2h4hjmlx2wh", "ebookssync");
        return SUCCESS;
    }

}
